package com.tmt.im.service.service;

import com.tmt.im.common.pojo.*;
import com.tmt.im.service.helper.IgniteQueryHelper;
import com.tmt.springboot.common.annotation._ReflectInvoked;
import lombok.extern.slf4j.Slf4j;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteSemaphore;
import org.apache.ignite.cache.query.FieldsQueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.MessageFormat;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 定时服务
 *
 * @Description TODO
 * @Author wuyi
 * @Date 2024/9/4 13:28
 * @Version 1.0
 **/
@Slf4j
@Service
public class TimedTaskService {

    private final Ignite ignite;

    private final IgniteCache<Long, ChatSessionPoJo> sessionCache;

    private final IgniteCache<SessionMemberKey, ChatSessionMemberPoJo> sessionMemberCache;

    private final IgniteCache<ChatDataKey, ChatDataPoJo> chatDataCache;

    private final IgniteCache<RedPackageDetailKey, RedPackageDetailPoJo> packageDetailCache;

    public TimedTaskService(Ignite ignite) {
        this.ignite = ignite;
        sessionCache = ignite.cache(ChatSessionPoJo.CACHE_NAME);
        sessionMemberCache = ignite.cache(ChatSessionMemberPoJo.CACHE_NAME);
        chatDataCache = ignite.cache(ChatDataPoJo.CACHE_NAME);
        packageDetailCache = ignite.cache(RedPackageDetailPoJo.CACHE_NAME);
    }

    @_ReflectInvoked("定时清除被删除的群组任务")
    @Scheduled(cron = "${timed-tasks.corn}")
    public void timedClearDeletedSession() throws Exception {
        log.info("--------定时清除被删除的群组任务-----开始-------");
        //使用全局信号量，防止其他实例的定时任务同时执行。
        try (IgniteSemaphore semaphore = ignite.semaphore("clear_deleted_session", 1, true, true)) {
            if (semaphore.tryAcquire(3, TimeUnit.SECONDS)) {
                try {
                    String sql = MessageFormat.format("select * from {0} where deleted = ?", ChatSessionPoJo.CACHE_NAME);
                    List<ChatSessionPoJo> sessionPoJos = IgniteQueryHelper.findAllBy(sql, new Object[]{true},
                            ChatSessionPoJo.class, sessionCache);
                    for (ChatSessionPoJo sessionPoJo : sessionPoJos) {
                        //检查是否存在未退款的红包详情信息。
                        sql = MessageFormat.format("select * from {0} where receivedAlready = ? and refunded = ? and groupId = ?",
                                RedPackageDetailPoJo.CACHE_NAME);
                        List<RedPackageDetailPoJo> list = IgniteQueryHelper.findAllBy(sql, new Object[]{false, false, sessionPoJo.getId()},
                                RedPackageDetailPoJo.class, packageDetailCache);
                        if (CollectionUtils.isEmpty(list)) {
                            _deleteSession(sessionPoJo);
                        }
                    }
                } catch (Exception ex) {
                    log.error(ex.getMessage(), ex);
                }
                log.info("--------定时清除被删除的群组任务-----结束-------");
            } else {
                log.info("--------定时清除被删除的群组任务-----结束(任务正在执行)-------");
            }
        }
    }

    private void _deleteSession(ChatSessionPoJo sessionPoJo) {
        String sqlTemplate = "delete from {0} where sessionId = ?";
        //删除聊天数据
        String sql = MessageFormat.format(sqlTemplate, ChatDataPoJo.CACHE_NAME);
        SqlFieldsQuery query = new SqlFieldsQuery(sql).setArgs(sessionPoJo.getId());
        try (FieldsQueryCursor<List<?>> cursor = chatDataCache.query(query)) {
            cursor.getAll();
        }

        //删除所有的聊天组成员。
        sql = MessageFormat.format(sqlTemplate, ChatSessionMemberPoJo.CACHE_NAME);
        query = new SqlFieldsQuery(sql).setArgs(sessionPoJo.getId());
        try (FieldsQueryCursor<List<?>> cursor = sessionMemberCache.query(query)) {
            cursor.getAll();
        }

        //删除聊天会话记录。
        sessionCache.remove(sessionPoJo.getKey());
    }

}
